#pragma once

#include "../comm/Util.hpp"
#include "compile.hpp"
#include "runner.hpp"
#include <jsoncpp/json/json.h>

#define TMP_FILE "./tmp/";

namespace ns_compile_run
{
    using namespace ns_compile;
    using namespace ns_runner;
    class compile_run
    {
    private:
    public:
        compile_run() {}
        ~compile_run() {}
        // 信号终止，返回错误信息串
        static std::string GetSigStr(int signum)
        {
            std::string ret;
            switch (signum)
            {
            case SIGABRT:
                ret = "内存超出限制";
                break;
            case SIGXCPU:
                ret = "时间超出限制";
                break;
            case SIGSEGV:
                ret = "段错误";
                break;
            case SIGFPE:
                ret = "浮点数异常";
                break;
            default:
                LOG(INFO) << "子进程终止,收到信号:" << signum << "\n";
                ret = "未知错误";
                break;
            }
            return ret;
        }
        // 传入相关临时文件名
        static void DeleTmpFile(const std::string file_name)
        {
            FileUtil::DeleFile(file_name);
            FileUtil::DeleFile(PathUtil::AddSuffixSrc(file_name));
            FileUtil::DeleFile(PathUtil::AddSuffixComErr(file_name));
            FileUtil::DeleFile(PathUtil::AddSuffixStderr(file_name));
            FileUtil::DeleFile(PathUtil::AddSuffixStdin(file_name));
            FileUtil::DeleFile(PathUtil::AddSuffixStdout(file_name));
        }
        /**********************************************************************
         * in_json:传入的json串。
         * out_json:返回的json串。
         * in_json结构:
         *  1.code(必填):为用户填写的代码。
         *  2.cpu_limit(必填):cpu最大运行时间。
         *  3.mem_limit(必填):内存最大限制。
         * out_json结构:
         *  1.ret_code:退出码。
         *    a.大于0:信号终止，值为对应信号。
         *    b.小于0:异常终止。（编译失败，或运行发生非信号错误）
         *    c.等于0:正常运行结束。(结果不一定正确)
         *  2.ret_out:程序运行完成返回输出结果
         *  3.ret_err:程序运行错误填充
         ***********************************************************************/
        static void Star(const std::string &in_json, std::string *out_json)
        {
            std::string ret_err;
            std::string ret_out;
            int ret_code;
            int run_code;
            int cpu_limit;
            int mem_limit;
            std::string file_name;
            std::string file_path;
            // 解析传入的字符串
            Json::Value in_value;
            Json::Reader reader;
            reader.parse(in_json, in_value);

            std::string code = in_value["code"].asString();
            if (code.size() == 0)
            {
                // 用户提交代码为空
                ret_code = -1;
                ret_err = "代码为空";
                goto END;
            }

            cpu_limit = in_value["cpu_limit"].asInt();
            mem_limit = in_value["mem_limit"].asInt();

            // 获取唯一性名字
            file_name = PathUtil::GetUniqueName();
            // 接上路径文件
            file_path = TMP_FILE;
            file_name.insert(0, file_path);
            // 将代码写入文件
            FileUtil::WriteFile(code, PathUtil::AddSuffixSrc(file_name));
            // 开始编译
            if (!compile::Compile(file_name))
            {
                // 编译失败
                FileUtil::ReadFile(ret_err, PathUtil::AddSuffixComErr(file_name));
                LOG(INFO) << "开始编译失败:" << ret_err << "\n";
                ret_code = -2;
                goto END;
            }
            // 开始运行
            run_code = runner::Run(file_name, cpu_limit, mem_limit);
            if (run_code > 0)
            {
                ret_err = GetSigStr(run_code);
                LOG(INFO) << "运行终止,终止原因:" << ret_err << "\n";
                ret_code = run_code;
            }
            else if (run_code < 0)
            {
                FileUtil::ReadFile(ret_err, PathUtil::AddSuffixStderr(file_name));
                LOG(INFO) << "运行错误,错误原因:" << ret_err << "\n";
                ret_code = -3;
            }
            else
            {
                FileUtil::ReadFile(ret_out, PathUtil::AddSuffixStdout(file_name));
                LOG(INFO) << "运行成功,输出:" << ret_out << "\n";
                ret_code = 0;
            }
        END:
            // 删除临时文件
            DeleTmpFile(file_name);

            // 将编译运行结果返回
            Json::Value out_value;
            out_value["ret_code"] = ret_code;
            out_value["ret_out"] = ret_out;
            out_value["ret_err"] = ret_err;
            Json::StyledWriter writer;
            *out_json = writer.write(out_value);
            // LOG(DEBUG) << "返回json串:" << *out_json << "\n";
        }
    };
}